#include <jni.h>

JNIEXPORT void JNICALL
Java_CPointer_copyIn_I_3III(JNIEnv *env, jobject self, jint boff, jintArray arr, jint off, jint len)
{
	 long peer = env->GetLongField(self, FID_CPointer_peer) ;
	 env->GetIntArrayRegion（arr, off, len, (jint *）peer+boff) ;
}
JNIEXPORT jlong JNICALL
Java_CMalloc_malloc(JNIEnv *env, jclass cls, jintsize)
{
	return (jlong) malloc(size) ;
}
JNIEXPORT void JNICALL
Java_CMalloc_free(JNIEnv *env, jclass self)
{
 	long  peer = env->GetLognField(self, FID_CPointer_peer) ;
 	free((void *)peer) ;
}

JNIEXPORT jlong JNICALL
Java_CFunction_find(JNIEnv *env, jobject self, jstring lib, jstring fun)
{
 void *handle ;
 void *func ;
 char *libname ;
 char *funname ;
 
 if( (libname = JNU_GetStringNativeChars(env, lib)) ){
  if( (funname = JNU_GetStringNativeChars(env, fun)) ){
   if ( (handle = LoadLibrary(libname)) ){
    if ( !(func = GetProcAddress(handle, funname)) ){
     JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", funname) ;
    }
   }else{
    JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", libname) ;
   }
   free(funname) ;
  }
  free(libname) ;
 }
 return (jlong)func ;
}
//进行了重分配到底层"C"函数的主要任务
JNIEXPORT jint JNICALL
Java_CFunction_callInt(JNIEnv *env, jobject self, jobjectArray arr)
{
#define MAX_NARGS 32
 jint ires ;
 int nargs, nwords ;
 jboolean is_string[MAX_NARGS] ;
 word_t args[MAX_NARGS] ;
 nargs = env->GetArrayLength(arr) ;
 if( nargs > MAX_NARGS ){
  JNU_ThrowByName(env,
    "java/lang/IllegalArgumentException",
    "too many arguments") ;
  return 0 ;
 }
 // convert arguments
 for ( nwords = 0 ; nwords < nargs ; nwords++ ){
  is_string[nwords] = JNI_FALSE ;
  jobject arg = env->GetObjectArrayElement(arr, nwords) ;
  if ( arg == NULL ){
   args[nwords].p = NULL ;
  }else if ( env->isInstatnceof(arg, Class_Integer)){
   args[nwords].i =
    env->GetIntField(arg, FID_Interger_value) ;
  }else if ( env->IsInstanceOf(arg, Class_Float)){
   args[nwords].f =
    env->GetFloatField(arg, FID_Float_value) ;
  }else if ( env->IsInstanceOf(arg, Class_CPointer) ){
   args[nwords].p = (void *)
    env->GetLongField(arg, FID_CPointer_peer) ;
  }else if ( env->IsInstanceOf(arg, Class_String) ){
   char *cstr =
    JNU_GetStringNativeChars(env, (jstring)arg) ;
   if ( (args[nwords].p = cstr) == NULL) {
    goto cleanup ;  // error thrown
   }
   is_string[nwords] = JNI_TRUE ;
  }else{
   JNU_ThrowByName(env,
     "java/lang/IllegalArgumentException",
     "unrecognized argument type") ;
   goto cleanup ;
  }
  env->DeleteLocalRef(arg) ;
 }
 void *func =
  (void *)env->GetLongField(self, FID_CPointer_peer) ;
 int conv = env->GetIntField(self, FID_CFunction_conv) ;
 // now transfer control to func.
 ires = asm_dispatch(func, nwords, args, conv) ;
cleanup:
 // free all the native string we have created
 for( int i = 0 ; i < nwords ; i++ ){
  if ( is_string[i] ){
   free(args[i].p) ;
  }
 }
 return ires ;
}

int asm_dispatch( void *func,  // pointer to the C function
   int nwords,  // number of words in args array
   word_t *args, // start of the argument data
   int conv)  // call convention 0: C
      //                 1: JNI
{
 __asm{
  mov esi, args
  mov edx nwords
  // Word address -> byte address
  shl edx, 2
  sub edx, 4
  jc args_done
  // push the last argument first
 args_loop:
  mov eax, DWORD PTR[esi+edx]
  push eax
  sub edx, 4
  jge SHORT args_loop
 args_done:
  call func
  // check for calling converntion
  mov edx, conv
  or edx, edx
  jnz jni_call
  // pop the arguments
  mov edx, nwords
  shl edx, 2
  add esp, edx
 jni_call:
  // done, return value in eax
 }
}